ES6介绍
阮一峰es6文档地址: https://es6.ruanyifeng.com/
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了也叫ECMAScript 2015。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言
(一) let 命令和const命令
知识点:
let的用法类似于var,用于变量的声明
使用let就会产生块级作用域,let命令只在块级作用域内(也就是大括号内)有效
let在同一作用域内只能声明一次, 不能重复声明
let和const不存在变量提升
详细例子:
1. let命令
<script>
//1.let块级作用域
{
var a = 100;
let b = 200;
}
console.log('a=',a);
// console.log('b=',b); // b只在{}内有效
for(let i=0;i<5;i++) {
}
// console.log(i); i只在{}内有效
</script>
2. const命令
<script>
// const用来声明常量,不能改变(不能重新赋值)
const PI = 3.1415926535;
// PI = 100;
// const 声明变量, 如果是变量是对象
// 对象不能重新赋值, 但是属性可用修改
const obj = {
name: '张三',
age: 100
}
// obj = {name:'lisi'}; // 常量不能重新赋值
obj.a = '李四';
</script>
3.不能重复声明
<script>
let a = 100;
let a = 200; // 会报错,a已经声明,不能重复声明
</script>
4.var、let、const 区别(背诵)
var 关键字的特点:
- 变量(预解析)提升,可以在声明的前面使用
- 同一作用域内可以多次声明同一个变量(即便这种方式不建议这样去写)
- 能让它形成作用域的只有函数
let:声明变量的关键字
- 没有变量提升,只能在声明之后使用
- 同一作用域内只能声明一次
- 你声明的变量的作用域仅限于最近的花括号{}
const:只能用来声明常量,该常量一旦声明其值就不能改变(与let的唯一区别)
- 没有变量提升,只能在声明之后使用
- 同一作用域内只能声明一次
- 你声明的变量的作用域仅限于最近的花括号{}内
- 用const声明的变量: 不允许重新赋值,引用数据类型可以添加或修改属性
(二) 变量的解构赋值
知识点:
解构: 结构分解, 从一个整体的变量里分解出一部分来使用
数组解构
对象解构
函数参数解构和默认值
// 1.数组和对象的解构
<script>
//数组解构
let [a,b,c] = [1,2,3];
console.log('a:',a); //值为1
let [p1,p2] = [{name: '张三'},{name: '李四'}];
console.log('P1:',p1); // [{name: '张三'}
//对象解构
let obj = {
username:'张三',
age: 100,
addr: '广东'
}
let {username,age} = obj;
console.log('username:',username); // 张三
console.log('age:',age); // 100
</script>
// 2.在函数中使用解构
<script>
function say({username,age}) {
let str = '他叫'+username+',他的年龄是'+age;
console.log(str);
}
let obj = {username:'李四',age:100}
say(obj);
</script>
// 3.默认值
<script>
let {} = ;
function say({username='张三',age=100}) {
let str = '他叫'+username+',他的年龄是'+age;
console.log(str);
}
let obj = {username:'李四',age:100}
// say(obj);
say({});
</script>
<script>
// data的默认值为{}, 若没有默认值{},当不传参数时会报错
function say(data={}) {
console.log(data.username);
}
say({username: '张三'});
say();
</script>
(三) 模板字符串
<!DOCTYPE html>
<html lang="en">
<body>
<script>
let username = '老张';
let age = 100;
// let str = '他叫'+username+',他老了';
let str = `他叫${username},他${age}了`;
let htmlStr = `<ul>
<li>${username}</li>
<li>${age}</li>
</ul>`;
</script>
</body>
</html>
(四) 对象的扩展
知识点:
属性和方法的简洁表示法
变量做属性名
合并对象
详细例子:
// 1.属性和方法的简洁表示法
<script>
let username = 'zhagnsan';
let age = 100;
// let obj = {
// username:username,
// age: age
// }
let obj = {
username,
age,
say() {
console.log(this.username);
}
}
console.log(obj);
</script>
// 2.变量做属性名
<script>
let a = 'username';
let b = 'age';
let obj = {
[a]: 'xxx',
[b]: 'yyy'
}
console.log(obj);
</script>
// 3.合并对象
<script>
let obj1 = {username:'zs'};
let obj2 = {age:100}
let obj = Object.assign(obj1,obj2);
console.log('obj',obj);
let a = {
username: '张三',
age: 100
}
let b = {
username: '李四',
age: 200,
addr: 'gd'
}
let c = Object.assign(a,b);
console.log('c',c); // {username:'李四',age:200,addr:'gd'}
</script>
(五) 函数的扩展: 箭头函数
知识点
箭头函数的常见表达方式
箭头函数的this指向:
专业说法: 由于箭头函数不绑定this, 它会捕获其所在上下文的this值, 作为自己的this值
大白话:拿别人的this当成是自己的, 表面现象就是箭头函数外面this是什么, 它的this就是什么
箭头函数不能做构造函数, 箭头函数的arguments对象不可用
详细例子
// 1. 箭头函数常见的表达方式
<script>
function add(a,b) {
return a+b;
}
// 1.箭头函数写法1
let add = (a,b)=> {
return a+b;
}
// 2.箭头的简写方式,函数体只有一行的时候,可以简写成
let add2 = (a,b)=>a+b;
// 3.当参数只有一个的时候,可以简写成:
let s1 = (num)=> {
return num*num;
}
// 简写
let s2 = num => num*num;
let list = [1,2,3];
let newList1 = list.map((item)=> {
return item*2;
});
// 简写
let newList2 = list.map(item=>item*2);
</script>
// 2. 箭头函数的this指向
<script>
let obj = {
say() {
console.log('say中的this',this);
setTimeout(function() {
console.log('普通函数,',this);
},1000);
setTimeout(()=>{
console.log('箭头函数',this);
},2000)
}
}
obj.say();
</script>
<script>
// 箭头函数不能做构造函数
// MadeCat是自定义构造函数,用来创建对象的
function MadeCat(name) {
this.name = name;
}
let cat = new MadeCat('小黑');
// 箭头函数不能做构造函数
let MadeCat2 = (name) => {
this.name = name;
}
let cat2 = new MadeCat2('小花');
// arguments对象
function add(){
console.log('arguments',arguments);
console.log('类型',Array.isArray(arguments));
}
add(1,2,3,4);
let add2 = () => {
// 箭头函数不存在arguments对象,所以会报错
console.log('arguments',arguments);
}
add2();
</script>
(六) 数组的扩展
知识点:
Array.from() // 将伪数组(类数组)变成真数组
find() // 找到了就返回符合条件的成员, 找不着就返回undefined
findIndex() // 找到了就返回符合条件的成员的下标, 找不着就返回undefined
includes() // 判断数组是否包含某个成员, 只能对数组成员是基本数据类型的数组使用
some() // 判断数组是否包含某个成员
keys() // 遍历键, 了解
values() // 遍历值, 了解
entries() // 遍历键值对, 了解
详细例子
// 1.Array.from
<script>
function add() {
let arg = Array.from(arguments);
console.log(arg);
console.log(Array.isArray(arg));
}
add(1,2,3);
</script>
// 2.find
<script>
let list = [{ username: 'zs', age: 21 }, { username: 'lisi', age: 20 }, { username: 'ww', age: 22 }, { username: 'lisi', age: 100 }];
let obj = list.find(item => item.username === 'lisan');
console.log('obj', obj);
</script>
// 3.findIndex
<script>
let list = [{ username: 'zs', age: 21 }, { username: 'lisi', age: 20 }, { username: 'ww', age: 22 }, { username: 'lisi', age: 100 }];
// let index = list.findIndex(function(item) {
// return item.username === 'ww';
// })
let index = list.findIndex(item => item.username === 'ww');
console.log('index',index);
</script>
(七) 扩展运算符 ...
知识点:
- 在对象中使用
- 在数组中使用
- 在函数中使用
详细例子:
<script>
let obj1 = {a:2,b:3,c:4};
let obj2 = {a:10,b:20,x:4};
// 1.合并两个对象, 属性相同, 后者覆盖前者
let obj = {
...obj1,
...obj2
}
console.log('obj',obj);
</script>
<script>
// 2.合并两个数组
let arr1 = [1,2,3];
let arr2 = [3,4,5]
let arr = [
...arr1,
...arr2
]
console.log('arr',arr);
</script>
// 3.在函数中使用
<script>
function add(num1,num2,...num3) {
console.log('num1:',num1); // 10
console.log('num2:',num2); // 20
console.log('num3:',num3); // [30,40,50]
}
add(10,20,30,40,50);
</script>
(八) Promise(背诵)
知识点:
promise定义
promise使用
promise的用途
(1) 什么是promise
promise中文意思承诺
promise有三种状态:
pending 正在进行中
resolved 成功
rejected 失败
promise状态一旦改变,就无法再次改变状态,这也是它名字 promise-承诺 的由来,一个promise对象只能改变一次
(2) promise的使用步骤:
- 创建promise对象
- 存储成功或失败的数据
- 获取promise对象的数据
// 1.创建一个简单的promise对象
<script>
let isSuccess = false;
// 1.1创建promise对象,接收一个函数作为参数
let promiseObj = new Promise((resolve,reject)=>{
// resolve()用来处理成功的情况
// reject()处理失败的情况
if (isSuccess) {
resolve({
code: 666,
msg: '成功了'
});
} else {
reject({
code: 500,
msg: '失败了'
})
}
});
// 1.2读取promise对象的值
promiseObj.then(res=> {
console.log('res',res);
}).catch(error=> {
console.log('error',error);
})
</script>
// 2.例子: axios.get()和axios.post()方法返回的都是一个Promise实例
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
var obj = axios.get('http://huruqing.cn:3003/category/all');
console.log(obj instanceof Promise);
// 因为obj是一个Promise的实例对象, 所以可以用.then()来获取数据
obj.then(res=> {
console.log(res);
}).catch(err=> {
console.log(err);
})
</script>
(3) promise的用途
promise是异步编程的一种解决方案, 是为了解决回调地狱的问题(核心在于async await)
// 3.1回调地狱
<script>
let isSuccess = true;
let promiseObj = new Promise((resolve, reject) => {
axios.get('').then(res=>{
axios.get('').then(res=> {
axios.get('').then(res=> {
resolve(res.data);
})
})
})
})
</script>
// 3.2 async await可以把异步变同步
<script>
let isSuccess = true;
let promiseObj = new Promise((resolve, reject) => {
setTimeout(() => {
if (isSuccess) {
resolve({msg:'成功'});
} else {
reject({msg:'成功'});
}
}, 5000)
})
// .then().catch()是异步的
// console.log(1);
// promiseObj.then(res=> {
// console.log(2);
// }).catch(err=> {
// console.log(err);
// })
// console.log(3);
// async await是同步的
console.log(1);
async function getData() {
// 可以对promise对象使用await,让异步变同步
console.log(2);
let res = await promiseObj;
console.log('res',res);
console.log(3);
}
getData();
console.log(4);
</script>
// 3.3解决回调地狱
<script>
let isSuccess = true;
let promiseObj1 = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve({msg:'success'})
},2000)
})
let promiseObj2 = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve({msg:'success'})
},4000)
})
let promiseObj3 = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve({msg:'success'})
},6000)
})
// 回调地狱
promiseObj1.then(res=> {
promiseObj2.then(res=> {
promiseObj3.then(res=> {
console.log(res);
})
})
})
// 使用async await把异步变同步
async function getData() {
let res1 = await promiseObj1;
let res2 = await promiseObj2;
let res3 = await promiseObj3;
console.log('res3',res3);
}
</script>
编程题: 根据提供的三个接口, 编写代码,找到广东分校web02班何秀英,并打印她的年龄
http://huruqing.cn:3009/getSchool 无需参数
http://huruqing.cn:3009/getClass // 需要schoolId
http://huruqing.cn:3009/getStudent // 需要参数classId
// 使用回调的方式解决
<script>
axios.get('http://huruqing.cn:3009/getSchool').then(res => {
// console.log(res.data);
// 查找广东分校
let school = res.data.find(item => item.schoolName === '广东分校');
// 获取schoolId
let {
schoolId
} = school;
// 根据schoolId获取班级列表
axios.get(`http://huruqing.cn:3009/getClass?schoolId=${schoolId}`).then(res => {
// 查找何秀英所在班级
let classObj = res.data.find(item => item.className === 'web02');
let {
classId
} = classObj;
// 根据classId查找学生列表
axios.get(`http://huruqing.cn:3009/getStudent?classId=${classId}`).then(res => {
// console.log(res.data);
let student = res.data.find(item => item.studentName === '何秀英');
console.log('何秀英的年龄是', student.age);
});
})
});
</script>
// 使用async await把异步变同步
<script>
// 封装请求函数
function getData(url) {
let promiseObj = new Promise((resolve, reject) => {
axios.get(url).then(res => {
resolve(res.data);
}).catch(err => {
reject(err);
});
})
return promiseObj;
}
async function getList() {
let url1 = 'http://huruqing.cn:3009/getSchool';
let schoolList = await getData(url1);
// 查找广东分校
let school = schoolList.find(item=>item.schoolName==='广东分校');
// 查找广东分校下的所有班级
let url2 = `http://huruqing.cn:3009/getClass?schoolId=${school.schoolId}`;
let classList = await getData(url2);
// 查找web02班
let classObj = classList.find(item=>item.className==='web02');
// 根据班级id查找学生
let url3 = `http://huruqing.cn:3009/getStudent?classId=${classObj.classId}`
let studentList = await getData(url3);
let student = studentList.find(item=>item.studentName==='何秀英');
console.log('何秀英的年龄是',student.age);
}
getList();
</script>
(九) ES6 模块系统
在html中使用模块
<script type="module"></script>
(1) 常用模块化规范:
commonjs规范 nodejs遵守commonjs规范
AMD规范 reqire.js遵守AMD规范
CMD规范 sea.js遵守CMD规范(玉伯, 淘宝)
ES6规范
(2) ES6模块导出和导入:
1. 导出和导入方式(一)
- export // 导出
- import {xx} from xxx // 导出名称是什么, 导入名称也是什么
// 导出 demo.js
export let username = '张三';
export let age = 100;
// 导入 demo.html
<script type="module">
import {username,age} from './demo.js';
console.log(username,age);
</script>
2. 导出和导入方式(二)
- export default // 默认导出
- import xx from xx // 导入,可以使用任意名称接收默认导出的变量
// 导出 demo.js
// var obj = {
// username: '张三',
// age:100
// }
// export default obj;
// 可以写成
export default {
username: '张三',
age:100
}
// 导入 demo.html
<script type="module">
import obj from './demo.js';
console.log(obj);
</script>
3. 重命名
- import {aa as xx} from xxx // 导入之后重命名
- import * as xx from xxx // 导入之后重命名
// 导出 demo.js
export let username = '张三';
export let age = 100;
// 导入1 demo.html
<script type="module">
import {username as uname,age} from './demo.js';
console.log(uname);
console.log(age);
</script>
// 导入2
<script type="module">
import * as obj from './demo.js';
console.log(obj);
</script>
(十) class
es5没有class的概念
- 声明一个类
- 类继承
// es6的类, 用来创建对象
class Person{
// 构造器(其实就是es5里的构造函数)
constructor(nation) {
this.nation = nation;
this.type = '人类';
}
say() {
console.log(`这是一个${this.nation}人`);
}
sing() {
console.log('人类会唱歌');
}
}
// 定义一个女人的类
class Woman extends Person{
constructor(nation) {
// 调用父类构造器
super(nation);
this.sex = '女人';
}
}
var w = new Woman('中国');
console.log('国籍',w.nation);
console.log('类别',w.type);
w.sing();
(十一) 新类型(了解)
map
set
symble
<script>
// Map数据结构
let map = new Map([['name','张三'],['age',100]]);
let name = map.get('name');
let age = map.get('age');
console.log('name=',name);
console.log('age=',age);
</script>
<script>
// Set数据结构
let arr = [1,43,5,2,76,5,1];
let set = new Set(arr);
// 可以使用...,把它变成数组,可以用来去重
let list = [...set];
console.log('list',list);
</script>
<script>
// symble是基本数据类型,使用symble创建的数据具有唯一性
let s1 = Symbol('aa');
let s2 = Symbol('aa');
console.log(s1 === s2); // false
</script>